/// @file Function Group State class models state of prescribed Function Groups.
#ifndef NOSAL_EXEC_FUNCTION_GROUP_STATE_H_
#define NOSAL_EXEC_FUNCTION_GROUP_STATE_H_

#include "nosal/exec/function_group.h"
#include "nosal/core/result.h"

namespace netaos {
namespace nosal {
namespace exec {

namespace {
const char kDelimiter = 3;
}
///
/// @brief Class representing Function Group State defined in the meta-model (ARXML).
///
/// @note Once created based on ARXML path, it's internal value stay bounded to it
///       for entire lifetime of an object.
///
class FunctionGroupState final
{
public:
    ///
    /// @brief Named constructor for FunctionGroupState.
    ///
    /// This method shall validate/verify meta-model path passed and perform FunctionGroupState object creation.
    ///
    /// @param functionGroup - the Function Group instance the state shall be connected with.
    /// @param metaModelIdentifier - stringified meta model identifier.
    /// @returns an instance of FunctionGroupState, or ExecErrorDomain error.
    /// @retval ExecErrc::kMetaModelError - if metaModelIdentifier passed is incorrect (e.g. FunctionGroup
    ///                                     identifier has been passed).
    /// @retval ExecErrc::kGeneralError - if any other error occurs.
    ///
    static nosal::core::Result<FunctionGroupState> Create(const FunctionGroup& functionGroup,
        std::string metaModelIdentifier) noexcept;

    ///
    /// @brief Default constructor.
    /// @note Default constructor is deleted in favor of named constructor (Create).
    ///
    FunctionGroupState() = delete;

    ///
    /// @brief Destructor of the FunctionGroupState instance.
    ///
    ~FunctionGroupState() noexcept;

    ///
    /// @brief Copy constructor.
    /// @note To prevent problems with resource allocations during copy operation, this class is non-copyable.
    ///
    FunctionGroupState(const FunctionGroupState&) = delete;

    ///
    /// @brief Copy assignment operator.
    /// @note To prevent problems with resource allocations during copy operation, this class is non-copyable.
    ///
    FunctionGroupState& operator=(const FunctionGroupState&) = delete;

    ///
    /// @brief Move constructor.
    /// @param[in] other FunctionGroupState instance to be moved to a newly constructed object.
    FunctionGroupState(FunctionGroupState&& other) noexcept;

    ///
    /// @brief Move assignment operator.
    /// @param[in] other FunctionGroupState instance to move to this object.
    FunctionGroupState& operator=(FunctionGroupState&& other) noexcept;

    ///
    /// @brief EQ operator to compare with other FunctionGroupState instance.
    ///
    /// @param other - FunctionGroupState instance to compare this one with.
    /// @returns true in case both FunctionGroupStates are representing exactly the same meta-model element,
    ///          false otherwise.
    ///
    bool operator==(const FunctionGroupState& other) const noexcept;

    ///
    /// @brief UNEQ operator to compare with other FunctionGroupState instance.
    ///
    /// @param other - FunctionGroupState instance to compare this one with.
    /// @returns false in case both FunctionGroupStates are representing
    ///          exactly the same meta-model element, true otherwise.
    ///
    bool operator!=(const FunctionGroupState& other) const noexcept;

private:
    /// @brief Private constructor used in Create method.
    explicit FunctionGroupState(FunctionGroup&& functionGroup, std::string metaModelIdentifier) noexcept;

    FunctionGroup group_;
    std::string metaModelIdentifier_;

    /// @brief Allow stringification of the FunctionGroupState by printing the group and the state's
    /// metaModelIdentifier.
    friend std::ostream& operator<<(std::ostream& os, const FunctionGroupState& state)
    {
        os << state.group_ << kDelimiter << state.metaModelIdentifier_;
        return os;
    }
};

}  // namespace exec
}  // namespace nosal
}  // namespace netaos

#endif  // NOSAL_EXEC_FUNCTION_GROUP_STATE_H
